home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
LANG
/
SCHEME
/
VSCM
/
doc
/
DESCRIPTIO
next >
Wrap
Text File
|
1994-08-05
|
18KB
|
673 lines
Improvements in V0r2 (over V0r1):
- numerous bugs in numeric code fixed
- numerous other bugs fixed
- subdirectory ``slib'' included (for SLIB support)
Improvements in V0r1 (over V0r0):
- bugs fixed
- new streamlined memory allocator / GC
- more support for files and file ports
- VM somewhat faster
- memory dump format much more compact
- portability problem in memory dump format eliminated (was
related to 64 bit machines like the DEC Alpha)
- error messages (somewhat) improved
Improvements (since vscmIISep29) relevant to public use:
- several bugs fixed
- support for coroutines added
- ``ticking'' (to allow for preemptive scheduling)
- multi-argument continuations
- interface to some extensions changed
- I/O interface generalized
- generic ports added
- ``string I/O'' added
- get and put!
Command line argument handling:
===============================
The following command line switches are recognized by VSCM:
-b bootfile
overrides DEFAULT_BOOTFILE and $VSCMBOOT (a definition of
the environment variable VSCMBOOT would take precedence
over DEFAULT_BOOTFILE)
-b -
does not load any bootfile
-a asmfile
reads VSCM assembly code definitions in asmfile after
loading the bootfile
-a -
reads assembly code in standard input after loading
the bootfile
-d dumpfile
writes system image into dumpfile immediately after
reading the bootfile (if any) and processing the asmfile
(if any).
-p dump_prefix
overrides DEFAULT_DUMP_PREFIX
this is used for the ``executable'' memory image
hack (see below)
The processing of these standard options is done left-to-right until
one of the following events (whichever comes first) occurs:
- there is no further command line argument
- the next argument does not start with ``-''
- the next argument is ``-'' by itself
- the next argument is ``--'' (``--'' will be skipped in this case)
All command line arguments not processed or skipped are passed to the
Scheme program. In what follows we will refer to those remaining
arguments as ``the arguments''. Here are the details:
1. on system startup (default boot image):
- the arguments are stored as a list into the global variable
command-line-arguments
- the arguments are interpreted as filenames and LOADed in
left-to-right order
2. After returning from ``(dump "filename")''.
- In the program (process) which originally executed
``(dump "filename")'' #f will be returned.
- In a process that was created by running VSCM with
``-b filename''
the call to ``dump'' returns a list of the arguments.
Note, that ``executing'' a memory image (the file written by
``dump'') is equivalent to running VSCM with the appropriate
``-b'' switch set.
Executable memory images:
=========================
I incorporated a cute hack suggested by Henry Cejtin (NEC) which
allows to ``run'' memory images directly. All which needed to be done
was:
- write a line of the form
#!/a/path/to/the/vscm/executable/here -b
into the first line of every memory image
- ignore the first line of every memory image
This works on all Unix systems which have the ``#!'' kernel hack. On
other systems it will not work (but it will not hurt either). VSCM
does not set permission bits to make the memory image executable --
this has to be done manually. (ANSI C does not provide a portable way
to set permission bits.)
Open compilation:
=================
Calls to the procedures NOT, CONS and any member of the (infinite!)
CAR/CDR family are ``open compiled'' (aka ``in-lined''). This allows
for better performance, but strictly speaking it also violates the
Scheme semantics: A subsequent redefinition of either of these
functions has no effect any more. Therefore, VSCM (like many other
Scheme implementations) offers to disable in-lining of these function
calls by running
(open-compilation #f)
Open compilation can be enabled again using
(open-compilation #t)
The function ``open-compilation'' always returns the old status.
While open compilation is enabled VSCM will refuse to accept any code
which (possibly) redefines or assigns to an open-compiled primitive.
Coroutines:
===========
The routines used to work with coroutines in VSCM are described below.
They can easily be implemented in any R4RS Scheme implementation using
``call-with-current-continuation''. Their implementation as
primitives was done because of efficiency considerations.
The coroutine interface was added to VSCM on demand by Greg Wilson.
Continuations with multiple arguments:
======================================
VSCM now provides full support for ``call-with-values'' and ``values''.
Moreover, the new facility was immediately used for other extensions
like ``divide'' and ``string-read'' (see description below).
Generic ports:
==============
VSCM now has a feature called ``generic ports''. Ports are treated as
an abstract data type supporting a number of operations. (Those are:
for input ports: read, read-char, peek-char, char-ready?, and close;
for output ports: write, display, write-char, newline, flush, close.)
VSCM makes no attempt to automatically enforce that ``write'' is
equivalent to so-many ``write-char''s. The behaviour is completely
in the hands of the programmer.
A straightforward implementation of ``string ports'' is given in the
appendix.
Reading from and writing to strings:
====================================
See description below.
This feature was added to allow the implementation of string ports (see
appendix).
Rudimentary file system interface:
==================================
VSCM now comes with procedures to remove and rename files.
File ports are more flexible:
=============================
The interface to the ``open-*-file'' procedures has been extended in a way
which resembles fopen's ``mode'' argument. It is possible to select
binary mode (as opposed to the default text mode), and you can ask for
permission to ``update'' a file (open for reading and writing at the same
time). Also, it is possible to specify which kind of buffering
(full, line, or none) is desired.
A ``seek-and-tell'' procedure was added. which essentially is a
combination of ``fseek'' and ``ftell''.
In addition to that you can open a ``temporary'' file (which is unnamed
and which automatically goes away after VSCM quits).
The timer:
==========
The timer was added to facilitate preemptive scheduling.
Get and put!:
=============
Property lists are now implemented.
Character names:
================
VSCM provides a somewhat richer syntax to specify character constants.
1. More symbolic character names:
#\Alarm ~=~ '\a'
#\Backspace ~=~ '\b'
#\Tab ~=~ '\t'
#\Newline ~=~ '\n'
#\VTab ~=~ '\v'
#\Return ~=~ '\r'
#\Escape ~=~ '\033'
#\Space ~=~ ' '
#\BackSlash ~=~ '\\'
2. Decimal, hexadecimal, octal, and binary notation
Decimal:
#\dn where n is a sequence of [0-9]
#\Dn
Hexadecimal:
#\xn where n is a sequence of [0-9a-fA-F]
#\Xn
Octal:
#\on where n is a sequence of [0-7]
#\On
Binary:
#\bn where n is a sequence of [01]
#\Bn
The numeric value of n must be within { 0, ..., 255 }, and the 1-1
mapping from those numeric values to character objects is the same
as the one used for integer->char and char->integer.
______________________________________________________________________________
VSCM procedures not present in R4RS -- a brief summary:
==============================================================
;;
;; Create a memory image of the running VSCM...
;;
(dump "filename")
- writes a memory image into file "filename" (see above)
;;
;; Execute a shell command...
;;
(system "shell command")
- return system ("shell command") == 0 ? #t : #f;
;;
;; Continuations with multiple arguments...
;;
(call-with-values thunk receiver)
- the R5RS (?) ``call-with-values'' primitive
(values obj ...)
- the R5RS (?) ``values'' primitive
;;
;; Handling errors...
;;
(with-error-handler handler thunk)
- equivalent to (thunk) as long as no error occurs
- calls (handler "error message" ``error-state'') in case of error
- handler MUST NEVER RETURN
- ``error-state'' is the continuation of the erroneous computation
- ``error-state'' CAN NOT BE INVOKED again
- ``error-state'' is for debugging (error inspection) only
;;
;; Controlling the garbage collector...
;;
(with-gc-strategy gc-strategy thunk)
- conceptually equivalent to (thunk) with gc-strategy in effect
- gc-strategy can be:
* #t - enables verbose GC messages (statistics)
* a user-supplied GC strategy (i.e. a Scheme procedure)
;;
;; Handling interrupts...
;;
(with-interrupt-handler handler thunk)
- without interrupts equivalent to (thunk)
- calls (handler) after SIGINT
- when (handler) returns the the execution of (thunk) resumes
;;
;; Raising an error condition...
;;
(error "error message")
- results in error with message "error message"
- can be caught by with-error-handler
;;
;; Cpu time measurements...
;;
(clock)
- returns number of milliseconds spent running VSCM so far
(gc-clock)
- returns number of milliseconds spent in VSCM's garbage
collector so far
;;
;; Accessing the environment...
;;
(getenv "environment variable")
- (getenv "XXX") returns "yyy" if "yyy" is the value of environment
variable XXX
- returns #f if XXX is not defined in environment
;;
;; Shutting down the system gracefully...
;;
(quit)
- exit (EXIT_SUCCESS);
(quit integer)
- exit (integer);
;;
;; The ubiquitous EVAL...
;;
(eval s-expr)
- evaluates s-expr in toplevel environment
;;
;; Controlling open compilation...
;;
(open-compilation boolean-flag)
- see above
;;
;; Modified interface to files and file ports...
;;
(remove-file "filename")
- does what it says (OS specific)
(rename-file "old-filename" "new-filename")
- does what it says (OS specific)
(with-input-from-port port thunk)
(with-output-to-port port thunk)
- do the obvious (analogous to ``with-input-from-file'' and
``with-output-to-file'')
(open-input-file "filename" [ updt [ binary [ bmode ] ] ])
(open-output-file "filename" [ updt [ binary [ bmode ] ] ])
- if ``updt'' then "+" is added to fopen's mode (open for update)
- if ``binary'' then "b" is added to fopen's mode (binary file)
- bmode == #t -> full buffering
#f -> no buffering
else line buffering
- defaults: updt = #f, binary = #f, bmode = #t
(open-append-file "filename" [ updt [ binary [ bmode ] ] ])
- similar to ``open-output-file''
- subsequent output operations write to the end of the file (fopen
is called with mode "a")
(open-temporary-file)
- returns a file port (as if opened with updt = #t, binary = #t,
bmode = #t)
- file is anonymous
- file is automatically removed when port is closed
(close-port port)
- closes any port (``close-input-port'' and ``close-output-port''
are aliased to this procedure)
(flush [output-port])
- writes any data buffered in the port to the external medium
- if the argument is missing then the current output port will be
``flush''ed
(seek-and-tell port offset whence)
- works for file ports only
- works only if the restrictions imposed on the undelying
``fseek'' are satisfied
- sets file position to ``w+offset'', where ``w'' is
- the beginning of the file if ``whence'' is #t
- the end of the file if ``whence'' is #f
- the current position otherwise
- returns the new position (as a number)
(standard-port filedes)
- filedes must be either 0, 1 or 2
- returns a port object for stdin, stdout or stderr, respectively
;;
;; Generic ports...
;;
(open-input-generic read read-char peek-char char-ready? close)
- returns a newly created generic input port object
- all arguments must be parameterless procedures
- subsequent calls to the primitives ``read'', ``read-char'',
``peek-char'', ``char-ready?'', and ``close-port'' with such a
port as the (implicit or explicit) argument are transformed
into calls to the respective procedure associated with the port
(open-output-generic write display write-char newline flush close)
- returns a newly created generic output port object
- all arguments must be procedures
- ``write'', ``display'', and ``write-char'' must accept one
argument
- ``newline'', ``flush'', and ``close'' are parameterless
- subsequent calls to the primitives ``write'', ``display'',
``write-char'', ``newline'', ``flush'', and ``close-port''
with such a port as the (implicit or explicit) argument are
transformed into calls to the respective procedure associated
with the port
;;
;; ``Writing'' to and ``reading'' from strings...
;;
(string-write obj)
- returns a newly allocated string containing the sequence of
characters that would have been sent to the output port by
``(write obj)''
(string-display obj)
- returns a newly allocated string containing the sequence of
characters that would have been sent to the output port by
``(display obj)''
(string-read "string")
- returns TWO values to the caller (similar to ``values'',
i.e. it requires ``call-with-values'')
- reads characters from "string" and builds an object just like
``read'' does when reading from a file port
- returns the new object AND a new string which contains the
remaining characters from the original string
(white space BEFORE the representation of the object will be
skipped, but all characters that originally came AFTER the
object's representation will be returned in the second value)
- if "string" is empty or contains only white space then
the first result will be the end-of-file object and the second
result will be an empty string
Example:
(call-with-values
(lambda () (string-read "(hello \"world\") @#$% this is Garbage"))
list)
=>
((hello "world") " @#$% this is Garbage")
;;
;; Another use of multiple values...
;;
(divide x y)
- returns TWO values to the caller
- is defined to behave as if it would be declared by:
(define (divide x y)
(values (quotient x y)
(remainder x y)))
- performs only one long division internally
;;
;; Timer...
;;
(timer [ticks])
- always returns the number of ticks left in the timer
- ``(timer 0)'' turns off the timer
- ``(timer n)'' with ``n'' being an exact integer > 0 sets the
number of ticks in the timer to ``n''
- the timer turns off itself upon expiration
- it is an error for the timer to expire with no ``timer expiration
handler'' defined in the current context
(with-timer-expiration-handler handler thunk)
- both arguments are procedures of 0 arguments
- ``thunk'' will be called and when the timer expires ``(handler)''
will run
- the computation of ``(thunk)'' resumes when ``handler'' returns
;;
;; Coroutines...
;;
(cr-create proc)
- returns a new coroutine object
- ``proc'' is a procedure of one argument, defining the body of the
new coroutine
- its argument will be supplied by the first ``cr-transfer''
to the newly created coroutine
(cr-transfer coroutine obj)
- transfers control to ``coroutine''
- ``obj'' is supplied to ``coroutine'' as the return value of
the most recent ``cr-transfer'' which was executed in the body
of ``coroutine'' or as the argument to ``proc'' (see ``cr-create'')
- the active coroutine is implicitly suspended
(cr-self)
- returns the coroutine object associated with the active coroutine
;;
;; Property lists:
;;
(get <symbol> <property>)
- <symbol> and <property> are Scheme symbols
- returns the property denoted by <property> of <symbol> or #f
if <property> was not defined for <symbol>
(put! <symbol> <property> <obj>)
- <symbol> and <property> are Scheme symbols
- <obj> can be any Scheme object
- (re-)defines the property <property> for <symbol> to be <obj>
(get-properties <symbol>)
- returns an A-list of <property> - <obj> pairs or #f if no
properties are defined
(set-properies! <symbol> <a-list>)
- replaces the properties of <symbol> by those defined in the
A-list <a-list>.
;;
;; Stuff you're not supposed to mess around with... :-)
;;
(execute-asm ...)
(define-asm ...)
(inspect ...)
- compiler/debugger/VM interface
______________________________________________________________________________
;;; Appendix: Implementation of string ports using generic ports
(define (open-input-string s)
(let ((l (string-length s))
(eof (call-with-values (lambda () (string-read "")) (lambda (x y) x))))
(define (read)
(call-with-values
(lambda ()
(string-read s))
(lambda (obj res)
(set! s res)
(set! l (string-length res))
obj)))
(define (read-char)
(if (zero? l)
eof
(let ((c (string-ref s 0)))
(set! s (substring s 1 l))
(set! l (- l 1))
c)))
(define (peek-char)
(if (zero? l) eof (string-ref s 0)))
(define (char-ready?) #t)
(define (close) s)
(open-input-generic read read-char peek-char char-ready? close)))
(define (open-output-string)
(let ((s ""))
(define (write x)
(set! s (string-append s (string-write x)))
x)
(define (display x)
(set! s (string-append s (string-display x)))
x)
(define (write-char x)
(set! s (string-append s (string x)))
x)
(define (newline)
(set! s (string-append s "\n"))
#f)
(define (flush) #f)
(define (close) s)
(open-output-generic write display write-char newline flush close)))